dropdown: Revise constructors
authorMatthias Clasen <mclasen@redhat.com>
Sun, 26 Jul 2020 13:34:08 +0000 (09:34 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Sun, 26 Jul 2020 22:09:54 +0000 (18:09 -0400)
A dropdown without a model is useless, so accept a model
and expression in the constructor. Allow them to be NULL,
but consume them if given. This makes chained constructors
convenient without breaking language bindings.

Drop gtk_drop_down_set_from_strings() and instead add
gtk_drop_down_new_from_strings().

Update all users.

13 files changed:
demos/gtk-demo/dropdown.c
demos/gtk-demo/listview_colors.c
docs/reference/gtk/gtk4-sections.txt
gtk/gtkcustompaperunixdialog.c
gtk/gtkdropdown.c
gtk/gtkdropdown.h
gtk/gtkfilechooserwidget.c
gtk/gtkprinteroptionwidget.c
gtk/inspector/controllers.c
gtk/inspector/prop-editor.c
gtk/inspector/size-groups.c
gtk/inspector/visual.c
tests/testdropdown.c

index bf82b9bd95b8b85fc6d26411fcf86d2bdf80cb34..dcd43203f53f6be741ec03f1de341d2b69820f37 100644 (file)
@@ -254,7 +254,7 @@ do_dropdown (GtkWidget *do_widget)
       gtk_widget_set_margin_bottom (box, 10);
       gtk_window_set_child (GTK_WINDOW (window), box);
 
-      button = gtk_drop_down_new ();
+      button = gtk_drop_down_new (NULL, NULL);
 
       model = G_LIST_MODEL (pango_cairo_font_map_get_default ());
       gtk_drop_down_set_model (GTK_DROP_DOWN (button), model);
index edbdb75c4dae104565a7950131c7d19547d3e7de..c252aab7dd64546fcb6f236a798ae01d868e02b3 100644 (file)
@@ -1003,8 +1003,7 @@ do_listview_colors (GtkWidget *do_widget)
       g_signal_connect (selection, "items-changed", G_CALLBACK (items_changed_cb), label);
       gtk_header_bar_pack_start (GTK_HEADER_BAR (header), label);
 
-      dropdown = gtk_drop_down_new ();
-      gtk_drop_down_set_from_strings (GTK_DROP_DOWN (dropdown), (const char *[]) { "8", "64", "512", "4096", "32768", "262144", "2097152", "16777216", NULL });
+      dropdown = gtk_drop_down_new_from_strings  ((const char * const[]) { "8", "64", "512", "4096", "32768", "262144", "2097152", "16777216", NULL });
       g_signal_connect (dropdown, "notify::selected",
                         G_CALLBACK (limit_changed_cb), 
                         gtk_sort_list_model_get_model (sort_model));
@@ -1082,7 +1081,7 @@ do_listview_colors (GtkWidget *do_widget)
       g_list_store_append (sorters, multi_sorter);
       g_object_unref (multi_sorter);
 
-      dropdown = gtk_drop_down_new ();
+      dropdown = gtk_drop_down_new (G_LIST_MODEL (sorters), NULL);
       box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
       gtk_box_append (GTK_BOX (box), gtk_label_new ("Sort by:"));
       gtk_box_append (GTK_BOX (box), dropdown);
@@ -1096,9 +1095,6 @@ do_listview_colors (GtkWidget *do_widget)
       gtk_drop_down_set_expression (GTK_DROP_DOWN (dropdown), expression);
       gtk_expression_unref (expression);
 
-      gtk_drop_down_set_model (GTK_DROP_DOWN (dropdown), G_LIST_MODEL (sorters));
-      g_object_unref (sorters);
-
       g_object_bind_property (dropdown, "selected-item", sort_model, "sorter", G_BINDING_SYNC_CREATE);
 
       factories = g_list_store_new (GTK_TYPE_LIST_ITEM_FACTORY);
@@ -1113,7 +1109,7 @@ do_listview_colors (GtkWidget *do_widget)
       set_title (factory, "Everything");
       g_list_store_append (factories, factory);
 
-      dropdown = gtk_drop_down_new ();
+      dropdown = gtk_drop_down_new (G_LIST_MODEL (factories), NULL);
       box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
       gtk_box_append (GTK_BOX (box), gtk_label_new ("Show:"));
       gtk_box_append (GTK_BOX (box), dropdown);
@@ -1127,9 +1123,6 @@ do_listview_colors (GtkWidget *do_widget)
       gtk_drop_down_set_expression (GTK_DROP_DOWN (dropdown), expression);
       gtk_expression_unref (expression);
 
-      gtk_drop_down_set_model (GTK_DROP_DOWN (dropdown), G_LIST_MODEL (factories));
-      g_object_unref (factories);
-
       g_object_bind_property (dropdown, "selected-item", gridview, "factory", G_BINDING_SYNC_CREATE);
     }
 
index 2881f94dbe0a4d88eaa4b836348ad683da8f284f..bc03daaac43f05c281b2a1b156697d27a73fb280 100644 (file)
@@ -7594,7 +7594,7 @@ gtk_string_filter_get_type
 <TITLE>GtkDropDown</TITLE>
 GtkDropDown
 gtk_drop_down_new
-gtk_drop_down_set_from_strings
+gtk_drop_down_new_from_strings
 gtk_drop_down_set_model
 gtk_drop_down_get_model
 gtk_drop_down_set_selected
index 6940fdf12aa0790cc40d0690bcdd7cc0de09f29f..8395b6cf4f3ce608333338b535c8e83587f1085c 100644 (file)
@@ -1022,8 +1022,7 @@ populate_dialog (GtkCustomPaperUnixDialog *dialog)
   gtk_grid_attach (GTK_GRID (grid), hbox, 0, 4, 2, 1);
   gtk_widget_show (hbox);
 
-  combo = gtk_drop_down_new ();
-  gtk_drop_down_set_model (GTK_DROP_DOWN (combo), dialog->printer_list);
+  combo = gtk_drop_down_new (g_object_ref (dialog->printer_list), NULL);
 
   factory = gtk_signal_list_item_factory_new ();
   g_signal_connect (factory, "setup", G_CALLBACK (setup_printer_item), dialog);
index 7b169ba780c1a38cbed4a843af5a121b5842cd26..05cb08f175008c3cd2a9a0fd38bfb15a398bfc4b 100644 (file)
@@ -62,9 +62,9 @@
  * and expects to obtain these from the model by evaluating an expression
  * that has to be provided via gtk_drop_down_set_expression().
  *
- * The convenience method gtk_drop_down_set_from_strings() can be used
- * to set up a model that is populated from an array of strings and
- * an expression for obtaining those strings.
+ * GtkDropDown knows how to obtain strings from the items in a
+ * #GtkStringList; for other models, you have to provide an expression
+ * to find the strings.
  *
  * GtkDropDown can optionally allow search in the popup, which is
  * useful if the list of options is long. To enable the search entry,
@@ -602,19 +602,47 @@ gtk_drop_down_init (GtkDropDown *self)
 
 /**
  * gtk_drop_down_new:
+ * @model: (transfer full) (allow-none): the model to use or %NULL for none
+ * @expression: (transfer full) (allow-none): the expression to use or %NULL for none
  *
- * Creates a new empty #GtkDropDown.
+ * Creates a new #GtkDropDown.
  *
- * You most likely want to call gtk_drop_down_set_factory() to
- * set up a way to map its items to widgets and gtk_drop_down_set_model()
- * to set a model to provide items next.
+ * You may want to call gtk_drop_down_set_factory()
+ * to set up a way to map its items to widgets.
  *
  * Returns: a new #GtkDropDown
  **/
 GtkWidget *
-gtk_drop_down_new (void)
+gtk_drop_down_new (GListModel    *model,
+                   GtkExpression *expression)
 {
-  return g_object_new (GTK_TYPE_DROP_DOWN, NULL);
+  GtkWidget *self;
+
+  self = g_object_new (GTK_TYPE_DROP_DOWN,
+                       "model", model,
+                       "expression", expression,
+                       NULL);
+
+  /* we're consuming the references */
+  g_clear_object (&model);
+  g_clear_pointer (&expression, gtk_expression_unref);
+
+  return self;
+}
+
+/**
+ * gtk_drop_down_new_from_strings:
+ * @strings: (array zero-terminated=1): The strings to put in the dropdown
+ *
+ * Creates a new #GtkDropDown that is populated with
+ * the strings in @strings.
+ *
+ * Returns: a new #GtkDropDown
+ */
+GtkWidget *
+gtk_drop_down_new_from_strings (const char * const *strings)
+{
+  return gtk_drop_down_new (G_LIST_MODEL (gtk_string_list_new (strings)), NULL);
 }
 
 /**
@@ -923,27 +951,3 @@ gtk_drop_down_get_expression (GtkDropDown *self)
 
   return self->expression;
 }
-
-/**
- * gtk_drop_down_set_from_strings:
- * @self: a #GtkDropDown
- * @texts: (array zero-terminated=1) (element-type utf8): a %NULL-terminated string array
- *
- * Populates @self with the strings in @text,
- * by creating a suitable model and factory.
- */
-void
-gtk_drop_down_set_from_strings (GtkDropDown       *self,
-                                const char *const *texts)
-{
-  GListModel *model;
-
-  g_return_if_fail (GTK_IS_DROP_DOWN (self));
-  g_return_if_fail (texts != NULL);
-
-  set_default_factory (self);
-
-  model = G_LIST_MODEL (gtk_string_list_new (texts));
-  gtk_drop_down_set_model (self, model);
-  g_object_unref (model);
-}
index 0795d0f77b2e0816ceb8bbf07f06596910264578..78438cab72c7a7cb987a7ed4c21b6a3ca2be8b2e 100644 (file)
@@ -31,11 +31,11 @@ GDK_AVAILABLE_IN_ALL
 G_DECLARE_FINAL_TYPE (GtkDropDown, gtk_drop_down, GTK, DROP_DOWN, GtkWidget)
 
 GDK_AVAILABLE_IN_ALL
-GtkWidget *     gtk_drop_down_new                               (void);
+GtkWidget *     gtk_drop_down_new                               (GListModel             *model,
+                                                                 GtkExpression          *expression);
 
 GDK_AVAILABLE_IN_ALL
-void            gtk_drop_down_set_from_strings                  (GtkDropDown            *self,
-                                                                 const char *const      *texts);
+GtkWidget *     gtk_drop_down_new_from_strings                  (const char * const *    strings);
 
 GDK_AVAILABLE_IN_ALL
 void            gtk_drop_down_set_model                         (GtkDropDown            *self,
index 44d6e856531678c7c45922df1b37734536635c89..3509cf7cf781aa62a7f65f4ebc17d7686b7865c0 100644 (file)
@@ -7918,19 +7918,14 @@ gtk_file_chooser_widget_add_choice (GtkFileChooser  *chooser,
     {
       GtkWidget *box;
       GtkWidget *combo;
-      GListModel *model;
 
       box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
       gtk_box_append (GTK_BOX (box), gtk_label_new (label));
 
-      combo = gtk_drop_down_new ();
+      combo = gtk_drop_down_new_from_strings ((const char * const *)options);
       g_hash_table_insert (impl->choices, g_strdup (id), combo);
       gtk_box_append (GTK_BOX (box), combo);
 
-      model = G_LIST_MODEL (gtk_string_list_new ((const char * const *)options));
-      gtk_drop_down_set_model (GTK_DROP_DOWN (combo), model);
-      g_object_unref (model);
-
       widget = box;
     }
   else
index 59cb79b1137bef7955cf54e9105cb1a947119301..200eef8a39355ef2aa67eb877619ccb31734cd91 100644 (file)
@@ -37,6 +37,7 @@
 #include "gtktogglebutton.h"
 #include "gtkorientable.h"
 #include "gtkprivate.h"
+#include "gtkstringlist.h"
 
 #include "gtkprinteroptionwidget.h"
 
@@ -479,7 +480,7 @@ combo_box_entry_new (void)
   gtk_widget_add_css_class (hbox, "linked");
 
   entry = gtk_entry_new ();
-  button = gtk_drop_down_new ();
+  button = gtk_drop_down_new (NULL, NULL);
   combo_box_set_model (button);
 
   factory = gtk_signal_list_item_factory_new ();
@@ -506,7 +507,7 @@ combo_box_new (void)
 {
   GtkWidget *combo_box;
 
-  combo_box = gtk_drop_down_new ();
+  combo_box = gtk_drop_down_new (NULL, NULL);
 
   combo_box_set_model (combo_box);
   combo_box_set_view (combo_box);
@@ -938,8 +939,7 @@ construct_widgets (GtkPrinterOptionWidget *widget)
       const char * strings[2];
       strings[0] = _("Not available");
       strings[1] = NULL;
-      priv->combo = gtk_drop_down_new ();
-      gtk_drop_down_set_from_strings (GTK_DROP_DOWN (priv->combo), strings);
+      priv->combo = gtk_drop_down_new_from_strings (strings);
       gtk_drop_down_set_selected (GTK_DROP_DOWN (priv->combo), 0);
       gtk_widget_set_sensitive (GTK_WIDGET (widget), FALSE);
       gtk_widget_show (priv->combo);
index a8fa4340ed7e073f562e2e56ff1c10edf8b376a4..0d5d1e7e41e52faae9987548eff38a43a2b87624 100644 (file)
@@ -148,8 +148,7 @@ create_controller_widget (gpointer item,
   phases[3] = C_("event phase", "Target");
   phases[4] = NULL;
 
-  dropdown = gtk_drop_down_new ();
-  gtk_drop_down_set_from_strings (GTK_DROP_DOWN (dropdown), phases);
+  dropdown = gtk_drop_down_new_from_strings (phases);
   gtk_drop_down_set_selected (GTK_DROP_DOWN (dropdown), gtk_event_controller_get_propagation_phase (controller));
   gtk_box_append (GTK_BOX (box), dropdown);
   gtk_widget_set_halign (label, GTK_ALIGN_END);
index fa586317b80fd41dd105ddaef8fdf046aeb2ebe7..26c586515a1385fe2fab02bb41b10672f8fe656d 100644 (file)
@@ -939,20 +939,16 @@ property_editor (GObject                *object,
     {
       {
         GEnumClass *eclass;
-        char **names;
+        GtkStringList *names;
         int j;
 
         eclass = G_ENUM_CLASS (g_type_class_ref (spec->value_type));
 
-        names = g_new (char *, eclass->n_values + 1);
+        names = gtk_string_list_new (NULL);
         for (j = 0; j < eclass->n_values; j++)
-          names[j] = (char *)eclass->values[j].value_name;
-        names[eclass->n_values] = NULL;
+          gtk_string_list_append (names, eclass->values[j].value_name);
 
-        prop_edit = gtk_drop_down_new ();
-        gtk_drop_down_set_from_strings (GTK_DROP_DOWN (prop_edit), (const char **)names);
-
-        g_free (names);
+        prop_edit = gtk_drop_down_new (G_LIST_MODEL (names), NULL);
 
         connect_controller (G_OBJECT (prop_edit), "notify::selected",
                             object, spec, G_CALLBACK (enum_modified));
@@ -1298,7 +1294,7 @@ attribute_editor (GObject                *object,
   gtk_box_append (GTK_BOX (box), button);
 
   gtk_box_append (GTK_BOX (box), gtk_label_new (_("Column:")));
-  dropdown = gtk_drop_down_new ();
+  dropdown = gtk_drop_down_new (NULL, NULL);
 
   store = g_list_store_new (ATTRIBUTE_TYPE_HOLDER);
   holder = attribute_holder_new (-1, TRUE);
index 83033ba21a1811067746e8351918bdda0efac168..21c351b8353795b2e69b06c790e3be97e2395908 100644 (file)
@@ -32,6 +32,7 @@
 #include "gtkswitch.h"
 #include "gtkwidgetprivate.h"
 #include "gtkstack.h"
+#include "gtkstringlist.h"
 
 
 typedef struct {
@@ -246,8 +247,7 @@ add_size_group (GtkInspectorSizeGroups *sl,
   gtk_widget_set_valign (label, GTK_ALIGN_BASELINE);
   gtk_box_append (GTK_BOX (box2), label);
 
-  dropdown = gtk_drop_down_new ();
-  gtk_drop_down_set_from_strings (GTK_DROP_DOWN (dropdown), modes);
+  dropdown = gtk_drop_down_new_from_strings (modes);
   g_object_set (dropdown, "margin", 10, NULL);
   gtk_widget_set_halign (dropdown, GTK_ALIGN_END);
   gtk_widget_set_valign (dropdown, GTK_ALIGN_BASELINE);
index 008b3e1ac7c82bdef5f8491d96b5e8b56a6dc220..fe8bc9954dd7f1fb2e34cb6e16cf6e48c3c482e6 100644 (file)
@@ -44,6 +44,7 @@
 #include "gtkbinlayout.h"
 #include "gtkeditable.h"
 #include "gtkentry.h"
+#include "gtkstringlist.h"
 
 #ifdef GDK_WINDOWING_X11
 #include "x11/gdkx.h"
@@ -502,13 +503,14 @@ theme_to_pos (GBinding *binding,
               GValue *to,
               gpointer user_data)
 {
-  char **names = user_data;
+  GtkStringList *names = user_data;
   const char *theme = g_value_get_string (from);
-  int i;
+  guint i, n;
 
-  for (i = 0; names[i]; i++)
+  for (i = 0, n = g_list_model_get_n_items (G_LIST_MODEL (names)); i < n; i++)
     {
-      if (strcmp (names[i], theme) == 0)
+      const char *name = gtk_string_list_get_string (names, i);
+      if (strcmp (name, theme) == 0)
         {
           g_value_set_uint (to, i);
           return TRUE;
@@ -523,9 +525,9 @@ pos_to_theme (GBinding *binding,
               GValue *to,
               gpointer user_data)
 {
-  char **names = user_data;
+  GtkStringList *names = user_data;
   int pos = g_value_get_uint (from);
-  g_value_set_string (to, names[pos]);
+  g_value_set_string (to, gtk_string_list_get_string (names, pos));
   return TRUE;
 }
 
@@ -537,9 +539,9 @@ init_theme (GtkInspectorVisual *vis)
   char *theme, *path;
   char **builtin_themes;
   GList *list, *l;
+  GtkStringList *names;
   guint i;
   const char * const *dirs;
-  char **names;
 
   t = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
   /* Builtin themes */
@@ -576,20 +578,19 @@ init_theme (GtkInspectorVisual *vis)
   while (g_hash_table_iter_next (&iter, (gpointer *)&theme, NULL))
     list = g_list_insert_sorted (list, theme, (GCompareFunc)strcmp);
 
-  names = g_new (char *, g_list_length (list) + 1);
+  names = gtk_string_list_new (NULL);
   for (l = list, i = 0; l; l = l->next, i++)
-    names[i] = g_strdup (l->data);
-  names[i] = NULL;
+    gtk_string_list_append (names, (const char *)l->data);
 
   g_list_free (list);
   g_hash_table_destroy (t);
 
-  gtk_drop_down_set_from_strings (GTK_DROP_DOWN (vis->theme_combo), (const char **)names);
+  gtk_drop_down_set_model (GTK_DROP_DOWN (vis->theme_combo), G_LIST_MODEL (names));
 
   g_object_bind_property_full (gtk_settings_get_for_display (vis->display), "gtk-theme-name",
                                vis->theme_combo, "selected",
                                G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE,
-                               theme_to_pos, pos_to_theme, names, (GDestroyNotify)g_strfreev);
+                               theme_to_pos, pos_to_theme, names, (GDestroyNotify)g_object_unref);
 
   if (g_getenv ("GTK_THEME") != NULL)
     {
@@ -654,8 +655,8 @@ init_icons (GtkInspectorVisual *vis)
   GHashTableIter iter;
   char *theme, *path;
   GList *list, *l;
-  char **names;
   int i;
+  GtkStringList *names;
 
   t = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 
@@ -672,20 +673,19 @@ init_icons (GtkInspectorVisual *vis)
   while (g_hash_table_iter_next (&iter, (gpointer *)&theme, NULL))
     list = g_list_insert_sorted (list, theme, (GCompareFunc)strcmp);
 
-  names = g_new (char *, g_list_length (list) + 1);
+  names = gtk_string_list_new (NULL);
   for (l = list, i = 0; l; l = l->next, i++)
-    names[i] = g_strdup (l->data);
-  names[i] = NULL;
+    gtk_string_list_append (names, (const char *)l->data);
 
   g_hash_table_destroy (t);
   g_list_free (list);
 
-  gtk_drop_down_set_from_strings (GTK_DROP_DOWN (vis->icon_combo), (const char **)names);
+  gtk_drop_down_set_model (GTK_DROP_DOWN (vis->icon_combo), G_LIST_MODEL (names));
 
   g_object_bind_property_full (gtk_settings_get_for_display (vis->display), "gtk-icon-theme-name",
                                vis->icon_combo, "selected",
                                G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE,
-                               theme_to_pos, pos_to_theme, names, (GDestroyNotify)g_strfreev);
+                               theme_to_pos, pos_to_theme, names, (GDestroyNotify)g_object_unref);
 }
 
 static void
@@ -720,7 +720,7 @@ init_cursors (GtkInspectorVisual *vis)
   GHashTableIter iter;
   char *theme, *path;
   GList *list, *l;
-  char **names;
+  GtkStringList *names;
   int i;
 
   t = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
@@ -738,20 +738,19 @@ init_cursors (GtkInspectorVisual *vis)
   while (g_hash_table_iter_next (&iter, (gpointer *)&theme, NULL))
     list = g_list_insert_sorted (list, theme, (GCompareFunc)strcmp);
 
-  names = g_new (char *, g_list_length (list) + 1);
+  names = gtk_string_list_new (NULL);
   for (l = list, i = 0; l; l = l->next, i++)
-    names[i] = g_strdup (l->data);
-  names[i] = NULL;
+    gtk_string_list_append (names, (const char *)l->data);
 
   g_hash_table_destroy (t);
   g_list_free (list);
 
-  gtk_drop_down_set_from_strings (GTK_DROP_DOWN (vis->cursor_combo), (const char **)names);
+  gtk_drop_down_set_model (GTK_DROP_DOWN (vis->cursor_combo), G_LIST_MODEL (names));
 
   g_object_bind_property_full (gtk_settings_get_for_display (vis->display), "gtk-cursor-theme-name",
                                vis->cursor_combo, "selected",
                                G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE,
-                               theme_to_pos, pos_to_theme, names, (GDestroyNotify)g_strfreev);
+                               theme_to_pos, pos_to_theme, names, (GDestroyNotify)g_object_unref);
 }
 
 static void
index d207256271e1079eeda085b2dab3c6ca7360faa9..5dcd7fcae79b74bf07afa25fc63374f2f9c4a845 100644 (file)
@@ -469,7 +469,7 @@ main (int argc, char *argv[])
   gtk_widget_set_margin_bottom (box, 10);
   gtk_window_set_child (GTK_WINDOW (window), box);
 
-  button = gtk_drop_down_new ();
+  button = gtk_drop_down_new (NULL, NULL);
 
   model = G_LIST_MODEL (pango_cairo_font_map_get_default ());
   gtk_drop_down_set_model (GTK_DROP_DOWN (button), model);
@@ -513,7 +513,7 @@ main (int argc, char *argv[])
   button = drop_down_new_from_strings (device_titles, device_icons, device_descriptions);
   gtk_box_append (GTK_BOX (box), button);
 
-  button = gtk_drop_down_new ();
+  button = gtk_drop_down_new (NULL, NULL);
 
   store = g_list_store_new (GTK_TYPE_STRING_PAIR);
   g_list_store_append (store, gtk_string_pair_new ("1", "One"));
@@ -536,7 +536,7 @@ main (int argc, char *argv[])
   gtk_widget_add_css_class (hbox, "linked");
 
   entry = gtk_entry_new ();
-  button = gtk_drop_down_new ();
+  button = gtk_drop_down_new (NULL, NULL);
 
   gtk_drop_down_set_model (GTK_DROP_DOWN (button), G_LIST_MODEL (store));